function mxConnector(points, stroke, strokewidth)
{
	this.points = points;
	this.stroke = stroke || 'black';
	this.strokewidth = strokewidth || 1;
};
mxConnector.prototype = new mxShape();
mxConnector.prototype.constructor = mxConnector;
mxConnector.prototype.mixedModeHtml = false;
mxConnector.prototype.preferModeHtml = false;
mxConnector.prototype.createHtml = function()
{
	var node = document.createElement('DIV');
	this.configureHtmlShape(node);
	node.style.borderStyle = 'none';
	node.style.background = '';
	return node;
};
mxConnector.prototype.createVml = function()
{
	var node = document.createElement('v:shape');
	this.strokeNode = document.createElement('v:stroke');
	this.configureVmlShape(node);
	this.strokeNode.setAttribute('endarrow', this.endArrow);
	this.strokeNode.setAttribute('startarrow', this.startArrow);

	if (this.opacity != null)
	{
		this.strokeNode.setAttribute('opacity', this.opacity + '%');
	}
	node.appendChild(this.strokeNode);
	return node;
};
mxConnector.prototype.redrawVml = function()
{
	if (this.node != null && this.strokeNode != null)
	{
		var startSize =
			mxUtils.getValue(this.style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_MARKERSIZE) * this.scale;
		var endSize =
			mxUtils.getValue(this.style, mxConstants.STYLE_ENDSIZE, mxConstants.DEFAULT_MARKERSIZE) * this.scale;
		var startWidth = 'medium';
		var startLength = 'medium';
		var endWidth = 'medium';
		var endLength = 'medium';

		if (startSize < 6)
		{
			startWidth = 'narrow';
			startLength = 'short';
		}
		else if (startSize > 10)
		{
			startWidth = 'wide';
			startLength = 'long';
		}

		if (endSize < 6)
		{
			endWidth = 'narrow';
			endLength = 'short';
		}
		else if (endSize > 10)
		{
			endWidth = 'wide';
			endLength = 'long';
		}
		this.strokeNode.setAttribute('startarrowwidth', startWidth);
		this.strokeNode.setAttribute('startarrowlength', startLength);
		this.strokeNode.setAttribute('endarrowwidth', endWidth);
		this.strokeNode.setAttribute('endarrowlength', endLength);
		this.updateVmlShape(this.node);
	}
};
mxConnector.prototype.createSvg = function()
{
	var g = this.createSvgGroup('path');
	var color = this.innerNode.getAttribute('stroke');

	if (this.startArrow != null)
	{
		this.start = document.createElementNS(mxConstants.NS_SVG, 'path');
		g.appendChild(this.start);
	}

	if (this.endArrow != null)
	{
		this.end = document.createElementNS(mxConstants.NS_SVG, 'path');
		g.appendChild(this.end);
	}

	this.pipe = document.createElementNS(mxConstants.NS_SVG, 'path');
	this.pipe.setAttribute('stroke', color);
	this.pipe.setAttribute('visibility', 'hidden');
	this.pipe.setAttribute('pointer-events', 'stroke');
	g.appendChild(this.pipe);
	return g;
};
mxConnector.prototype.redrawSvg = function()
{
	mxShape.prototype.redrawSvg.apply(this, arguments);
	var strokeWidth = this.strokewidth * this.scale;
	var color = this.innerNode.getAttribute('stroke');

	if (mxConstants.SVG_CRISP_EDGES && strokeWidth == Math.floor(strokeWidth) && !this.isRounded)
	{
		this.node.setAttribute('shape-rendering', 'optimizeSpeed');
	}
	else
	{
		this.node.setAttribute('shape-rendering', 'auto');
	}

	if (this.points != null && this.points[0] != null)
	{
		if (this.start != null)
		{
			var p0 = this.points[1];
			var pe = this.points[0];
			var size = mxUtils.getValue(this.style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_MARKERSIZE);
			this.startOffset = this.redrawSvgMarker(this.start, this.startArrow, p0, pe, color, size);
		}

		if (this.end != null)
		{
			var n = this.points.length;
			var p0 = this.points[n - 2];
			var pe = this.points[n - 1];
			var size = mxUtils.getValue(this.style, mxConstants.STYLE_ENDSIZE, mxConstants.DEFAULT_MARKERSIZE);
			this.endOffset = this.redrawSvgMarker(this.end, this.endArrow, p0, pe, color, size);
		}
	}
	this.updateSvgShape(this.innerNode);
	var d = this.innerNode.getAttribute('d');

	if (d != null)
	{
		this.pipe.setAttribute('d', this.innerNode.getAttribute('d'));
		this.pipe.setAttribute('stroke-width', strokeWidth + mxShape.prototype.SVG_STROKE_TOLERANCE);
	}
	this.innerNode.setAttribute('fill', 'none');
};
mxConnector.prototype.redrawSvgMarker = function(node, type, p0, pe, color, size)
{
	var offset = null;
	var dx = pe.x - p0.x;
	var dy = pe.y - p0.y;
	var dist = Math.max(1, Math.sqrt(dx * dx + dy * dy));
	var absSize = size * this.scale;
	var nx = dx * absSize / dist;
	var ny = dy * absSize / dist;
	pe = pe.clone();
	pe.x -= nx * this.strokewidth / (2 * size);
	pe.y -= ny * this.strokewidth / (2 * size);
	nx *= 0.5 + this.strokewidth / 2;
	ny *= 0.5 + this.strokewidth / 2;

	if (type == 'classic' || type == 'block')
	{
		var d = 'M ' + pe.x + ' ' + pe.y + ' L ' + (pe.x - nx - ny / 2) + ' ' + (pe.y - ny + nx / 2)
			+ ((type != 'classic') ? '' : ' L ' + (pe.x - nx * 3 / 4) + ' ' + (pe.y - ny * 3 / 4)) + ' L '
			+ (pe.x + ny / 2 - nx) + ' ' + (pe.y - ny - nx / 2) + ' z';
		node.setAttribute('d', d);
		offset = new mxPoint(-nx * 3 / 4, -ny * 3 / 4);
	}
	else if (type == 'open')
	{
		nx *= 1.2;
		ny *= 1.2;
		var d =
			'M ' + (pe.x - nx - ny / 2) + ' ' + (pe.y - ny + nx / 2) + ' L ' + (pe.x - nx / 6) + ' ' + (pe.y - ny / 6)
			+ ' L ' + (pe.x + ny / 2 - nx) + ' ' + (pe.y - ny - nx / 2) + ' M ' + pe.x + ' ' + pe.y;
		node.setAttribute('d', d);
		node.setAttribute('fill', 'none');
		node.setAttribute('stroke-width', this.scale * this.strokewidth);
		offset = new mxPoint(-nx / 4, -ny / 4);
	}
	else if (type == 'oval')
	{
		nx *= 1.2;
		ny *= 1.2;
		absSize *= 1.2;
		var d =
			'M ' + (pe.x - ny / 2) + ' ' + (pe.y + nx / 2) + ' a ' + (absSize / 2) + ' ' + (absSize / 2) + ' 0  1,1 '
			+ (nx / 8) + ' ' + (ny / 8) + ' z';
		node.setAttribute('d', d);
	}
	else if (type == 'diamond')
	{
		var d = 'M ' + (pe.x + nx / 2) + ' ' + (pe.y + ny / 2) + ' L ' + (pe.x - ny / 2) + ' ' + (pe.y + nx / 2) + ' L '
			+ (pe.x - nx / 2) + ' ' + (pe.y - ny / 2) + ' L ' + (pe.x + ny / 2) + ' ' + (pe.y - nx / 2) + ' z';
		node.setAttribute('d', d);
	}
	node.setAttribute('stroke', color);

	if (type != 'open')
	{
		node.setAttribute('fill', color);
	}
	else
	{
		node.setAttribute('stroke-linecap', 'round');
	}

	if (this.opacity != null)
	{
		node.setAttribute('fill-opacity', this.opacity / 100);
		node.setAttribute('stroke-opacity', this.opacity / 100);
	}
	return offset;
};